/**
 * 
 */
package both.map.mapModel.unitTests;

import junit.framework.Assert;
import org.junit.Test;
import both.map.TerrainType;
import both.map.mapModel.TerrainCell;

/**
 * @author jdl
 *
 */
public class TerrainCellTest {
	/**
	 * Test terrain type with constructors and getTerrainType().
	 */
	@Test
	public void testTerrainCellTerrainType() 
	{
		TerrainCell tc;
		tc = new TerrainCell();
		
		Assert.assertEquals("Blank TerrainCell constructor should make empty.", 
							TerrainType.empty, tc.getTerrainType());
		 
		tc = new TerrainCell(TerrainType.empty);
		
		Assert.assertEquals("TerrainCellConstructor with TerrainType.empty",
							TerrainType.empty, tc.getTerrainType());
		
		tc = new TerrainCell(TerrainType.grass);
		
		Assert.assertEquals("TerrainCell constructor with TerrainType.grass",
							TerrainType.grass, tc.getTerrainType());	
	}
	
	/**
	 * Test TerrainCell constructors against runtime problems.
	 */
	@Test
	public void testTerrainCell() {
		@SuppressWarnings("unused")
		TerrainCell tc = new TerrainCell();
		tc = new TerrainCell(TerrainType.empty);
		tc = new TerrainCell(TerrainType.grass);
	}

	/**
	 * Test method for reassignTerrain().
	 */
	@Test
	public void testReassignTerrain() {
		TerrainCell tc = new TerrainCell();
		Assert.assertEquals("TerrainCell constructor with no argument failed", TerrainType.empty, tc.getTerrainType());
		tc.reassignTerrain(TerrainType.empty);
		Assert.assertEquals("TerrainCell not reassigned empty", TerrainType.empty, tc.getTerrainType());
		tc.reassignTerrain(TerrainType.grass);
		Assert.assertEquals("TerrainCell not reassigned grass", TerrainType.grass, tc.getTerrainType());
		tc.reassignTerrain(TerrainType.empty);
		Assert.assertEquals("TerrainCell not reassigned empty after other", TerrainType.empty, tc.getTerrainType());
		
		// make sure it doesn't work when part of an update
		tc = new TerrainCell();
		tc.reassignTerrain(TerrainType.mud);
		TerrainCell update = tc.grabUpdate();
		
		Assert.assertFalse(update.reassignTerrain(TerrainType.sand));
		Assert.assertNotSame(TerrainType.sand, update.getTerrainType());
	}

	/**
	 * Test updates.
	 */
	@Test
	public void testUpdate() {
		TerrainCell serTC = new TerrainCell();
		TerrainCell cliTC = new TerrainCell();
		TerrainCell update = serTC.grabUpdate();
		Assert.assertNull("Should be null update when no changes made since construction",
							update);
		cliTC.applyUpdate(update);
		Assert.assertEquals(TerrainType.empty, cliTC.getTerrainType());
		
		
		// Update round 1
		serTC.reassignTerrain(TerrainType.gravel);
		update = serTC.grabUpdate();
		Assert.assertNotNull("Update should not be null after updated", update);
		Assert.assertEquals("Update terrainType should match gravel", 
							TerrainType.gravel, update.getTerrainType());
		
		cliTC.applyUpdate(update);
		Assert.assertEquals(TerrainType.gravel, cliTC.getTerrainType());
		
		Assert.assertNull("TerrainCell.grabUpdate should be null after update grabbed",
							serTC.grabUpdate());
		
		// Update round 2: update TerrainType same as before
		serTC.reassignTerrain(TerrainType.gravel);
		update = serTC.grabUpdate();
		Assert.assertNotNull("Update round 2: shouldn't be null after update", update);
		Assert.assertEquals("Update round 2: update terraintype should match gravel, ",
							TerrainType.gravel, update.getTerrainType());
		
		cliTC.applyUpdate(update);
		Assert.assertEquals(TerrainType.gravel, cliTC.getTerrainType());
		
		Assert.assertNull("Update round 2: grabUpdate should be null after update", serTC.grabUpdate());
		
		// Update round 3
		serTC.reassignTerrain(TerrainType.stoneWall);
		update = serTC.grabUpdate();
		Assert.assertNotNull("Update round 3: shouldn't be null after update", update);
		Assert.assertEquals("Update round 3: update terraintype should match stonewall, ",
							TerrainType.stoneWall, update.getTerrainType());
		
		cliTC.applyUpdate(update);
		Assert.assertEquals(TerrainType.stoneWall,cliTC.getTerrainType());
		
		Assert.assertNull("Update round 3: grabUpdate should be null after update", serTC.grabUpdate());
	}
}
